package com.ljf.daily.softwareautorecord.domain.service;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ljf.common.domain.service.BasisDomainService;
import com.ljf.common.exception.ServiceException;
import com.ljf.common.utils.CollectionUtil;
import com.ljf.common.utils.DateUtil;
import com.ljf.config.domain.repository.ConfigDatRecordSymbolRepository;
import com.ljf.config.dto.query.ConfigDatRecordSymbolQuery;
import com.ljf.config.enums.ConfigDatRecordSymbolTypeEnum;
import com.ljf.config.vo.ConfigDatRecordSymbolVO;
import com.ljf.daily.makemoneysoftware.domain.repository.DailyDatMakeMoneySoftwareRepository;
import com.ljf.daily.softwareautorecord.domain.repository.DailyDatSoftwareAutoRecordRepository;
import com.ljf.daily.softwareautorecord.domain.repository.DailyDatSoftwareAutoWithdrawalRepository;
import com.ljf.daily.softwareautorecord.dto.command.DailyDatSoftwareAutoRecordCommand;
import com.ljf.daily.makemoneysoftware.dto.query.DailyDatMakeMoneySoftwareQuery;
import com.ljf.daily.softwareautorecord.dto.query.DailyDatSoftwareAutoRecordQuery;
import com.ljf.daily.softwareautorecord.dto.query.DailyDatSoftwareAutoWithdrawalQuery;
import com.ljf.daily.softwareautorecord.enums.DailyDatSoftwareAutoRecordModeTypeEnum;
import com.ljf.daily.makemoneysoftware.model.DailyDatMakeMoneySoftware;
import com.ljf.daily.softwareautorecord.model.DailyDatSoftwareAutoRecord;
import com.ljf.daily.softwareautorecord.model.DailyDatSoftwareAutoWithdrawal;
import com.ljf.daily.makemoneysoftware.vo.DailyDatMakeMoneySoftwareVO;
import com.ljf.daily.softwareautorecord.vo.DailyDatSoftwareAutoRecordVO;
import com.ljf.daily.softwareautorecord.vo.DailyDatSoftwareAutoWithdrawalVO;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 赚钱软件自动记录  领域服务
 *
 * @author LJF
 * @since 2024-12-14
 */
@Component
@AllArgsConstructor
public class DailyDatSoftwareAutoRecordDomainService extends BasisDomainService<DailyDatSoftwareAutoRecordRepository, DailyDatSoftwareAutoRecordQuery, DailyDatSoftwareAutoRecordVO, DailyDatSoftwareAutoRecord, DailyDatSoftwareAutoRecordCommand> {

    private final DailyDatMakeMoneySoftwareRepository makeMoneySoftwareRepository;
    private final ConfigDatRecordSymbolRepository configDatRecordSymbolRepository;
    private final DailyDatSoftwareAutoWithdrawalRepository withdrawalRepository;

    @Override
    public DailyDatSoftwareAutoRecord add(DailyDatSoftwareAutoRecordCommand command) throws ServiceException {
        DailyDatSoftwareAutoRecord model = super.add(command);
        withdrawalRepository.insert(
                DailyDatSoftwareAutoWithdrawal.builder()
                        .softwareAutoCode(model.getCode())
                        .withdrawalCount(command.getWithdrawalCount())
                        .build()
        );
        return model;
    }

    @Override
    public boolean deleteBatch(List<Long> ids) throws ServiceException {
        if (CollectionUtil.isNotEmpty(ids)) {
            List<DailyDatSoftwareAutoRecordVO> modelList = repository.selectListByIds(ids);
            List<String> codeList = modelList.stream()
                    .map(DailyDatSoftwareAutoRecordVO::getCode).distinct().collect(Collectors.toList());
            withdrawalRepository.delete(DailyDatSoftwareAutoWithdrawalQuery.builder().softwareAutoCodeList(codeList).build());
        }
        return super.deleteBatch(ids);
    }

    @Override
    public Boolean edit(DailyDatSoftwareAutoRecordCommand command) throws ServiceException {
        super.edit(command);
        DailyDatSoftwareAutoRecordVO model = repository.selectById(command.getId());
        withdrawalRepository.update(
                DailyDatSoftwareAutoWithdrawal.builder().withdrawalCount(command.getWithdrawalCount()).build(),
                DailyDatSoftwareAutoWithdrawalQuery.builder().softwareAutoCode(model.getCode()).build()
        );
        return true;
    }

    @Override
    public Page<DailyDatSoftwareAutoRecordVO> query(DailyDatSoftwareAutoRecordQuery query) throws ServiceException {
        Page<DailyDatSoftwareAutoRecordVO> page = super.query(query);
        if (page.getTotal() > 0L) {
            List<DailyDatSoftwareAutoRecordVO> resultList = page.getRecords();
            List<String> softwareCodeList = resultList.stream()
                    .map(DailyDatSoftwareAutoRecordVO::getSoftwareCode).distinct().collect(Collectors.toList());
            List<DailyDatMakeMoneySoftwareVO> softwareList = makeMoneySoftwareRepository.selectList(
                    DailyDatMakeMoneySoftwareQuery.builder().codeList(softwareCodeList).build()
            );
            Map<String, String> softwareNameMap = softwareList.stream().collect(Collectors.toMap(
                    DailyDatMakeMoneySoftwareVO::getCode, DailyDatMakeMoneySoftwareVO::getName, (a, b) -> a)
            );
            List<String> symbolCodeList = resultList.stream()
                    .map(DailyDatSoftwareAutoRecordVO::getSymbolCode).distinct().collect(Collectors.toList());
            List<ConfigDatRecordSymbolVO> recordSymbolList = configDatRecordSymbolRepository.selectList(
                    ConfigDatRecordSymbolQuery.builder().codeList(symbolCodeList).build()
            );
            Map<String, String> recordSymbolMap = recordSymbolList.stream().collect(Collectors.toMap(
                    ConfigDatRecordSymbolVO::getCode, ConfigDatRecordSymbolVO::getName, (a, b) -> a)
            );
            for (DailyDatSoftwareAutoRecordVO result : resultList) {
                result.setSoftwareName(softwareNameMap.getOrDefault(result.getSoftwareCode(), ""));
                result.setSymbolName(recordSymbolMap.getOrDefault(result.getSymbolCode(), ""));
            }
            this.fillWithdrawal(resultList);
        }
        return page;
    }

    @Override
    public DailyDatSoftwareAutoRecordVO queryById(Long id) throws ServiceException {
        DailyDatSoftwareAutoRecordVO model = super.queryById(id);
        DailyDatSoftwareAutoWithdrawalVO withdrawalModel = withdrawalRepository.selectOne(
                DailyDatSoftwareAutoWithdrawalQuery.builder().softwareAutoCode(model.getCode()).build()
        );
        model.setWithdrawalCount(withdrawalModel.getWithdrawalCount());
        return model;
    }

    /**
     * 获取模板
     *
     * @param date
     * @param symbolCode
     * @return
     * @throws ServiceException
     */
    public List<DailyDatSoftwareAutoRecordVO> queryTemplate(Date date, String symbolCode) throws ServiceException {
        List<DailyDatSoftwareAutoRecordVO> resultList = new ArrayList<>();
        resultList.addAll(this.queryTemplateByDay(symbolCode));
        resultList.addAll(this.queryTemplateByMonth(date, symbolCode));
        resultList.addAll(this.queryTemplateByYear(date, symbolCode));
        if (CollectionUtil.isNotEmpty(resultList)) {
            List<String> softCodeList = resultList.stream().map(DailyDatSoftwareAutoRecordVO::getSoftwareCode)
                    .distinct().collect(Collectors.toList());
            List<DailyDatMakeMoneySoftwareVO> softwareList = makeMoneySoftwareRepository.selectList(
                    DailyDatMakeMoneySoftwareQuery.builder().codeList(softCodeList).build()
            );
            Map<String, DailyDatMakeMoneySoftwareVO> softwareMap = softwareList.stream().collect(
                    Collectors.toMap(DailyDatMakeMoneySoftwareVO::getCode, Function.identity(), (a, b) -> a)
            );
            for (DailyDatSoftwareAutoRecordVO result : resultList) {
                if (softwareMap.containsKey(result.getSoftwareCode())) {
                    result.setSoftwareName(softwareMap.get(result.getSoftwareCode()).getName());
                    result.setAccountCode(softwareMap.get(result.getSoftwareCode()).getAccountCode());
                    result.setAccountName(softwareMap.get(result.getSoftwareCode()).getAccountName());
                    result.setBelongDate(DateUtil.addDate(date, result.getDateOffset()));
                }
            }
            this.fillWithdrawal(resultList);
        }
        return resultList;
    }

    /**
     * 查询赚钱软件自动记录标签
     *
     * @return
     * @throws ServiceException
     */
    public List<ConfigDatRecordSymbolVO> querySymbol() throws ServiceException {
        return configDatRecordSymbolRepository.selectList(
                ConfigDatRecordSymbolQuery.builder()
                        .type(ConfigDatRecordSymbolTypeEnum.DAILY_DAT_SOFTWARE_AUTO_RECORD.getCode())
                        .build()
        );
    }

    /**
     * 填充提现金额
     *
     * @param resultList
     * @throws ServiceException
     */
    private void fillWithdrawal(List<DailyDatSoftwareAutoRecordVO> resultList) throws ServiceException {
        if (CollectionUtil.isEmpty(resultList)) {
            return;
        }
        List<String> autoCodeList = resultList.stream()
                .map(DailyDatSoftwareAutoRecordVO::getCode).distinct().collect(Collectors.toList());
        List<DailyDatSoftwareAutoWithdrawalVO> autoWithdrawalList = withdrawalRepository.selectList(
                DailyDatSoftwareAutoWithdrawalQuery.builder().softwareAutoCodeList(autoCodeList).build()
        );
        Map<String, BigDecimal> withdrawalMap = autoWithdrawalList.stream().collect(
                Collectors.toMap(DailyDatSoftwareAutoWithdrawalVO::getSoftwareAutoCode,
                        DailyDatSoftwareAutoWithdrawalVO::getWithdrawalCount,
                        (a, b) -> a)
        );
        for (DailyDatSoftwareAutoRecordVO result : resultList) {
            result.setWithdrawalCount(withdrawalMap.getOrDefault(result.getCode(), BigDecimal.ZERO));
        }
    }

    /**
     * 获取模板-每天
     *
     * @param symbolCode
     * @return
     * @throws ServiceException
     */
    private List<DailyDatSoftwareAutoRecordVO> queryTemplateByDay(String symbolCode) throws ServiceException {
        return repository.selectList(
                DailyDatSoftwareAutoRecordQuery.builder()
                        .modeType(DailyDatSoftwareAutoRecordModeTypeEnum.DAY.getCode())
                        .symbolCode(symbolCode)
                        .build()
        );
    }

    /**
     * 获取模板-按月
     *
     * @param date
     * @param symbolCode
     * @return
     * @throws ServiceException
     */
    private List<DailyDatSoftwareAutoRecordVO> queryTemplateByMonth(Date date, String symbolCode) throws ServiceException {
        int day = DateUtil.getDay(date);
        return repository.selectList(
                DailyDatSoftwareAutoRecordQuery.builder()
                        .modeType(DailyDatSoftwareAutoRecordModeTypeEnum.MONTH.getCode())
                        .symbolCode(symbolCode)
                        .executionDate(day)
                        .build()
        );
    }

    /**
     * 获取模板-按年
     *
     * @param date
     * @param symbolCode
     * @return
     * @throws ServiceException
     */
    private List<DailyDatSoftwareAutoRecordVO> queryTemplateByYear(Date date, String symbolCode) throws ServiceException {
        int day = DateUtil.getDay(date);
        int month = DateUtil.getMonth(date) + 1;
        return repository.selectList(
                DailyDatSoftwareAutoRecordQuery.builder()
                        .modeType(DailyDatSoftwareAutoRecordModeTypeEnum.YEAR.getCode())
                        .symbolCode(symbolCode)
                        .executionDate(month * 100 + day)
                        .build()
        );
    }

}
